package com.baijia.services.impl;

import com.baijia.authentication.AccountType;
import com.baijia.common.enums.UserRoleType;
import com.baijia.dao.OrgAccountDao;
import com.baijia.dao.OrgCascadeAccountDao;
import com.baijia.dao.PassportDao;
import com.baijia.dao.UserDao;
import com.baijia.dao.UserRegisterLogDao;
import com.baijia.dao.po.Passport;
import com.baijia.dao.po.User;
import com.baijia.dao.po.UserRegisterLog;
import com.baijia.services.PassportService;
import com.baijia.util.JacksonUtil;
import com.baijia.util.JigouPasswordUtil;
import com.baijia.util.MobileLoginUtil;
import com.baijia.util.SerialNumberUtil;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpStatus;
import org.apache.logging.log4j.util.Strings;
import org.codehaus.jackson.type.TypeReference;
import org.json.JSONArray;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * Created by bjhl on 16/4/25.
 */
@Service
public class PassportServiceImpl implements PassportService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private PassportDao passportDao;

    @Resource
    private UserDao userDao;

    @Resource
    private OrgAccountDao orgAccountDao;

    @Resource
    private OrgCascadeAccountDao orgCascadeAccountDao;

    @Resource
    private UserRegisterLogDao userRegisterLogDao;

    @Value("${URL.PAY.SERVER}")
    private String PAY_SERVER;

    @Value("${URL.PATH.BANK.CARD.LIST}")
    private String PATH_BANK_CARD_LIST;

    @Value("${URL.PATH.CHANGE.MOBILE.VERIFY}")
    private String PATH_CHANGE_MOBILE_VERIFY;

    @Value("${PAY_TOKEN}")
    private String PAY_TOKEN;

    @Override
    public boolean existedUserI18n(String countrySymbol, String countryCode, String mobile, int appId) {
        if (AccountType.USER.getCode() == appId || AccountType.ORG_TEACHER.getCode() == appId) { // User表数据
            mobile = MobileLoginUtil.getI18nMobile(countrySymbol, countryCode, mobile);
        }

        // FIXME 机构只使用了手机号，没验证country_code字段
        return existedUser(mobile, appId);
    }

    @Override
    public boolean existedUser(String mobile, int appId) {
        AccountType accountType = AccountType.getAccountTypeByCode(appId);

        switch (accountType) {
            case ORG:
                return orgAccountDao.findByMobile(mobile, Strings.EMPTY) != null;
            case ORG_SUB_ACCT:
                return orgCascadeAccountDao.findByUsername(mobile) != null;
            case USER:
            case ORG_TEACHER:
                return userDao.getUserByMobile(mobile) != null;
            case PASSPORT:
            default:
                return passportDao.findByMobile(mobile) != null;
        }
    }

    @Override
    public long createAccount(Passport passport) {
        return passportDao.savePassport(passport);
    }

    public long synUserData(Passport passport) {
        User user = new User();
        user.setMobile(passport.getMobile());
        user.setPassword(passport.getPassword());
        user.setEmail(StringUtils.isEmpty(passport.getEmail()) ? null : passport.getEmail());
        Long lastInsertId = userDao.save(user);
        long number =
            SerialNumberUtil.generateNumberNoSuffix(lastInsertId.intValue(), SerialNumberUtil.MAX) * 10
                + SerialNumberUtil.USER_SUFFIX;// 8 普通用户 9 机构用户
        userDao.updateNumber(lastInsertId, number);
        return lastInsertId;
    }

    @Override
    @Transactional
    public int synData(Passport passport) {
        long userId = synUserData(passport);
        // FIXME 机构数据表存在问题 未来处理
        // long orgId = synOrgData(passport);
        long orgId = 0;
        return passportDao.updateUserIdAndOrgId(passport.getId(), userId, orgId);
    }

    @Override
    public int updatePwd(Long passportId, String newPwd) {
        return passportDao.updatePwd(passportId, newPwd);

    }

    @Override
    public Passport getById(Long id) {
        return passportDao.getById(id);
    }

    @Override
    public int updatePwdByMobile(String password, String mobile) {
        String pwdHash = JigouPasswordUtil.createHash(password);
        return passportDao.updatePwdByMobile(pwdHash, mobile);
    }

    @Override
    public boolean updateMobile(String mobile, Long passportId) {
        if (StringUtils.isEmpty(mobile) || passportId == null) {
            logger.warn("updateMobile : params invalid");
            return false;
        }

        return passportDao.updateMobileById(mobile, passportId) == 1;
    }

    @Override
    public int createUser(Passport passport, HttpServletRequest request) {
        User user = new User();
        user.setMobile(passport.getMobile());
        user.setPassword(passport.getPassword());
        user.setEmail(StringUtils.isEmpty(passport.getEmail()) ? null : passport.getEmail());
        Long lastInsertId = userDao.save(user);
        long number =
            SerialNumberUtil.generateNumberNoSuffix(lastInsertId.intValue(), SerialNumberUtil.MAX) * 10
                + SerialNumberUtil.USER_SUFFIX;// 8 普通用户 9 机构用户
        userDao.updateNumber(lastInsertId, number);

        UserRegisterLog userRegisterLog = setUserRegisterLog(request);
        userRegisterLog.setUserId(lastInsertId);
        return userRegisterLogDao.save(userRegisterLog);
    }

    @Override
    public boolean changeMobileVerify(HttpServletRequest request) {

        String url = PAY_SERVER + PATH_CHANGE_MOBILE_VERIFY;

        Map<String, Object> params = Maps.newHashMapWithExpectedSize(7);
        genBankCardInfoParams(params, request);

        String type = request.getParameter("type");
        params.put("type", type);

        String data = JSONObject.toJSONString(params);
        String sign = DigestUtils.md5Hex(data + DigestUtils.md5Hex(PAY_TOKEN));
        params.put("sign", sign);

        if ("0".equals(type)) { // 银行卡信息验证
            String bankCard = request.getParameter("bankCard");
            String cardNo = request.getParameter("cardNo");
            String idCard = request.getParameter("idCard");
            params.put("bankCard", bankCard);
            params.put("cardNo", cardNo);
            params.put("idCard", idCard);
        } else if ("1".equals(type)) { // 支付密码验证信息
            String password = request.getParameter("payPassword");
            params.put("password", password);
        }

        HttpResponse<JsonNode> response;
        try {
            logger.info("changeMobileVerify: request params: {}", params);
            response = Unirest.post(url).queryString(params).asJson();

            if (response != null) {
                logger.debug("changeMobileVerify: response status={}", response.getStatus());
                if (response.getStatus() == HttpStatus.SC_OK) {
                    org.json.JSONObject result = response.getBody().getObject();
                    logger.info("changeMobileVerify: response from pay server: {}", result);
                    if (0 == result.getInt("code") && true == result.getBoolean("data")) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("changeMobileVerify: error!", e);
        }

        return false;
    }

    private void genBankCardInfoParams(Map<String, Object> params, HttpServletRequest request) {
        String numberStr = request.getParameter("userId");
        Long number = Long.parseLong(numberStr);

        String userRoleStr = request.getParameter("userRole");
        Integer userRole = Integer.parseInt(userRoleStr);

        Long userId = 0L;
        UserRoleType userRoleType = UserRoleType.getById(userRole);
        switch (userRoleType) {
            case ORG:
                userId = orgAccountDao.getIdByNumber(number);
                break;
            case STUDENT:
            case TEACHER:
                userId = userDao.getIdByNumber(number);
                break;
            default:
                break;
        }

        params.put("user_id", String.valueOf(userId));
        params.put("user_role", userRoleStr);
    }

    @Override
    public List<Map<String, Object>> getBankCardInfo(HttpServletRequest request) {

        String url = PAY_SERVER + PATH_BANK_CARD_LIST;

        Map<String, Object> params = Maps.newHashMapWithExpectedSize(3);
        genBankCardInfoParams(params, request);

        String data = JSONObject.toJSONString(params);
        String sign = DigestUtils.md5Hex(data + DigestUtils.md5Hex(PAY_TOKEN));
        params.put("sign", sign);

        HttpResponse<JsonNode> response;
        try {
            logger.info("getBankCardInfo: request params: {}", params);
            response = Unirest.post(url).queryString(params).asJson();

            if (response != null) {
                logger.debug("getBankCardInfo: response status={}", response.getStatus());
                if (response.getStatus() == HttpStatus.SC_OK) {
                    logger.info("getBankCardInfo: response from pay server: {}", response.getBody().getObject());
                    JSONArray tmpResult = response.getBody().getObject().getJSONArray("data");

                    List<Map<String, Object>> result =
                        JacksonUtil.str2Obj(tmpResult.toString(), new TypeReference<List<Map<String, Object>>>() {
                        });

                    return result;
                }
            }
        } catch (Exception e) {
            logger.warn("getBankCardInfo: get response from pay server error!", e);
        }

        return null;
    }

    public static void main(String[] args) {
        Map<String, Object> params = Maps.newHashMapWithExpectedSize(3);
        String videoInfoUrl = "http://test-pay.genshuixue.com/wallet/cardListForChangeMobile";
        params.put("user_id", "3334295");
        params.put("user_role", "2");
        String data = JSONObject.toJSONString(params);
        String token = "bjhl83242355@kkfsges";
        String sign = DigestUtils.md5Hex(data + DigestUtils.md5Hex(token));
        params.put("sign", sign);

        HttpResponse<JsonNode> response;
        try {
            response = Unirest.post(videoInfoUrl).queryString(params).asJson();
            if (response.getStatus() == HttpStatus.SC_OK) {
                JSONArray result = response.getBody().getObject().getJSONArray("data");
                System.out.println(result);
            }
        } catch (UnirestException e) {
            e.printStackTrace();
        } catch (JSONException e) {

        }
    }

    private UserRegisterLog setUserRegisterLog(HttpServletRequest request) {
        UserRegisterLog userRegisterLog = new UserRegisterLog();
        String userRole = request.getParameter("user_role");
        if (org.apache.commons.lang.StringUtils.isNotBlank(userRole)) {
            userRegisterLog.setUserRole(Integer.valueOf(userRole));
        }
        String client = request.getParameter("client");
        if (org.apache.commons.lang.StringUtils.isNotBlank(client)) {
            userRegisterLog.setClient(Integer.valueOf(client));
        }
        userRegisterLog.setVersion(request.getParameter("version"));
        userRegisterLog.setChannel(request.getParameter("channel"));
        userRegisterLog.setChannelId(request.getParameter("channel_id"));
        userRegisterLog.setIp(request.getParameter("ip"));
        userRegisterLog.setDevice(request.getParameter("device"));

        return userRegisterLog;
    }

    // private long synOrgData(Passport passport) {
    // OrgAccount orgAccount = new OrgAccount();
    // orgAccount.setMobile(passport.getMobile());
    // orgAccount.setPassword(passport.getPassword());
    // Long lastInsertId = orgAccountDao.save(orgAccount);
    // long number =
    // SerialNumberUtil.generateNumberNoSuffix(lastInsertId.intValue(), SerialNumberUtil.MAX) * 10
    // + SerialNumberUtil.ORG_SUFFIX;// 8 普通用户 9 机构用户
    // orgAccountDao.updateNumber(lastInsertId, number);
    // return lastInsertId;
    // }

}
